/**
 * WiFi通信服务
 * 提供WiFi设备的连接与通信功能
 */

const AppConfig = require('../config/app.config');
const logger = require('../utils/logger').logger;
const envDetector = require('../utils/env-detector');
const connectionStatus = require('../utils/connection-status');

// WiFi连接状态
const CONNECTION_STATUS = {
  DISCONNECTED: 0,  // 未连接
  CONNECTING: 1,    // 连接中
  CONNECTED: 2,     // 已连接
  ERROR: 3          // 连接错误
};

// 健康检查状态
const HEALTH_STATUS = {
  EXCELLENT: 3,     // 优良
  GOOD: 2,          // 良好
  POOR: 1,          // 较差
  OFFLINE: 0        // 离线
};

/**
 * WiFi服务类
 */
class WifiService {
  constructor() {
    this.deviceMap = new Map();         // 设备ID到连接状态的映射
    this.isInitialized = false;         // WiFi模块是否已初始化
    this.healthCheckInterval = null;    // 健康检查定时器
    this.pingResults = new Map();       // 设备ID到ping结果的映射
    this.reconnectTimers = new Map();   // 重连定时器
    this.maxRetryCount = 3;             // 最大重试次数
    this.retryDelays = [2000, 5000, 10000]; // 重试间隔时间（递增）
    this.isDevTools = envDetector.isDevTools(); // 是否为开发者工具环境
    
    // 初始化WiFi模块
    this._initializeWifi();
  }

  /**
   * 初始化WiFi模块
   * @private
   */
  _initializeWifi() {
    this.isInitialized = false;
    
    // 开发者工具环境下使用模拟模式
    if (this.isDevTools) {
      logger.info('开发者工具环境: 使用WiFi模拟模式');
      this.isInitialized = true;
      
      // 模拟WiFi连接状态变化
      this._mockWifiConnectedEvent();
      
      // 初始化健康检查
      this._startHealthCheck();
      return;
    }
    
    wx.startWifi({
      success: (res) => {
        logger.info('WiFi模块初始化成功', res);
        this.isInitialized = true;
        
        // 监听WiFi连接状态变化
        wx.onWifiConnected((res) => {
          logger.info('WiFi连接状态变化', res);
          const { wifi } = res;
          
          if (wifi) {
            // WiFi已连接
            this._handleWifiConnected(wifi);
          } else {
            // WiFi已断开
            this._handleWifiDisconnected();
          }
        });
        
        // 初始化健康检查
        this._startHealthCheck();
      },
      fail: (err) => {
        logger.error('WiFi模块初始化失败', err);
        this.isInitialized = false;
        
        // 尝试重新初始化
        setTimeout(() => {
          this._initializeWifi();
        }, 5000);
      }
    });
  }

  /**
   * 模拟WiFi连接事件（开发者工具环境下使用）
   * @private
   */
  _mockWifiConnectedEvent() {
    if (!this.isDevTools) return;
    
    logger.info('模拟WiFi连接事件');
    
    // 模拟数据
    const mockWifi = {
      SSID: 'MockWiFi',
      BSSID: 'aa:bb:cc:dd:ee:ff',
      secure: true,
      signalStrength: 90
    };
    
    // 模拟WiFi连接事件
    setTimeout(() => {
      this._handleWifiConnected(mockWifi);
    }, 1000);
  }

  /**
   * 处理WiFi连接成功
   * @param {Object} wifi - WiFi连接信息
   * @private
   */
  _handleWifiConnected(wifi) {
    // 找到对应的设备
    this.deviceMap.forEach((status, deviceId) => {
      const device = this.deviceMap.get(deviceId);
      if (device && (!device.bssid || device.bssid === wifi.BSSID)) {
        // 更新设备状态
        device.status = CONNECTION_STATUS.CONNECTED;
        device.ssid = wifi.SSID;
        device.signalStrength = wifi.signalStrength;
        
        // 触发连接成功回调
        if (device.onConnected) {
          device.onConnected(wifi);
        }
        
        // 清除重连定时器
        if (this.reconnectTimers.has(deviceId)) {
          clearTimeout(this.reconnectTimers.get(deviceId));
          this.reconnectTimers.delete(deviceId);
        }
      }
    });
  }

  /**
   * 处理WiFi断开连接
   * @private
   */
  _handleWifiDisconnected() {
    // 更新所有设备的状态
    this.deviceMap.forEach((device, deviceId) => {
      if (device.status === CONNECTION_STATUS.CONNECTED) {
        device.status = CONNECTION_STATUS.DISCONNECTED;
        
        // 触发断开连接回调
        if (device.onDisconnected) {
          device.onDisconnected();
        }
        
        // 自动重连
        this._startAutoReconnect(deviceId);
      }
    });
  }

  /**
   * 开始自动重连
   * @param {string} deviceId - 设备ID
   * @private
   */
  _startAutoReconnect(deviceId) {
    const device = this.deviceMap.get(deviceId);
    if (!device || !device.autoReconnect) return;
    
    // 已有重连定时器，先清除
    if (this.reconnectTimers.has(deviceId)) {
      clearTimeout(this.reconnectTimers.get(deviceId));
    }
    
    // 重置重试计数
    device.retryCount = 0;
    
    // 启动重连
    this._scheduleReconnect(deviceId);
  }

  /**
   * 安排重连
   * @param {string} deviceId - 设备ID 
   * @private
   */
  _scheduleReconnect(deviceId) {
    const device = this.deviceMap.get(deviceId);
    if (!device) return;
    
    // 超过最大重试次数
    if (device.retryCount >= this.maxRetryCount) {
      logger.warn(`设备[${deviceId}]重连失败，已达到最大重试次数`);
      
      // 触发重连失败回调
      if (device.onReconnectFailed) {
        device.onReconnectFailed();
      }
      return;
    }
    
    // 获取重试延迟
    const delay = this.retryDelays[device.retryCount] || this.retryDelays[this.retryDelays.length - 1];
    
    // 设置重连定时器
    const timer = setTimeout(() => {
      logger.info(`尝试重新连接设备[${deviceId}]，第${device.retryCount + 1}次重试`);
      
      // 增加重试计数
      device.retryCount += 1;
      
      // 连接WiFi
      this.connectToDevice(deviceId, {
        onSuccess: () => {
          logger.info(`设备[${deviceId}]重连成功`);
          // 清除重连定时器
          this.reconnectTimers.delete(deviceId);
        },
        onFailed: () => {
          logger.warn(`设备[${deviceId}]重连失败，将再次尝试`);
          // 继续重连
          this._scheduleReconnect(deviceId);
        }
      });
    }, delay);
    
    // 记录定时器
    this.reconnectTimers.set(deviceId, timer);
  }

  /**
   * 开始WiFi健康检查
   * @private
   */
  _startHealthCheck() {
    // 先停止现有的健康检查
    this._stopHealthCheck();
    
    // 开始新的健康检查
    this.healthCheckInterval = setInterval(() => {
      // 对所有已连接的设备进行健康检查
      this.deviceMap.forEach((device, deviceId) => {
        if (device.status === CONNECTION_STATUS.CONNECTED) {
          this._checkDeviceHealth(deviceId);
        }
      });
    }, AppConfig.WIFI.HEALTH_CHECK_INTERVAL || 30000); // 默认30秒检查一次
  }

  /**
   * 停止WiFi健康检查
   * @private
   */
  _stopHealthCheck() {
    if (this.healthCheckInterval) {
      clearInterval(this.healthCheckInterval);
      this.healthCheckInterval = null;
    }
  }

  /**
   * 检查设备健康状态
   * @param {string} deviceId - 设备ID
   * @private
   */
  _checkDeviceHealth(deviceId) {
    const device = this.deviceMap.get(deviceId);
    if (!device) return;
    
    // 开发者工具环境下模拟健康检查
    if (this.isDevTools) {
      this._mockHealthCheck(deviceId);
      return;
    }
    
    // 获取当前WiFi信息
    wx.getConnectedWifi({
      success: (res) => {
        const wifi = res.wifi;
        
        // 确认是否连接到目标设备
        if (wifi && wifi.BSSID === device.bssid) {
          // 更新信号强度
          device.signalStrength = wifi.signalStrength;
          
          // 执行ping测试
          this._pingDevice(deviceId);
          
          // 计算健康分数
          const healthScore = this._calculateHealthScore(deviceId);
          device.healthStatus = healthScore;
          
          // 触发健康状态更新回调
          if (device.onHealthUpdate) {
            device.onHealthUpdate({
              deviceId,
              signalStrength: device.signalStrength,
              pingResult: this.pingResults.get(deviceId),
              healthStatus: healthScore
            });
          }
          
          // 如果健康状态为离线，尝试重连
          if (healthScore === HEALTH_STATUS.OFFLINE) {
            logger.warn(`设备[${deviceId}]健康检查失败，尝试重连`);
            this._startAutoReconnect(deviceId);
          }
        }
      },
      fail: (err) => {
        logger.error(`获取设备[${deviceId}]WiFi连接信息失败`, err);
        
        // 设置设备为断开状态
        device.status = CONNECTION_STATUS.DISCONNECTED;
        
        // 触发断开连接回调
        if (device.onDisconnected) {
          device.onDisconnected();
        }
        
        // 自动重连
        this._startAutoReconnect(deviceId);
      }
    });
  }

  /**
   * 模拟健康检查（开发者工具环境下使用）
   * @param {string} deviceId - 设备ID
   * @private
   */
  _mockHealthCheck(deviceId) {
    const device = this.deviceMap.get(deviceId);
    if (!device) return;
    
    // 模拟信号强度 (70-100之间随机)
    device.signalStrength = 70 + Math.floor(Math.random() * 30);
    
    // 模拟ping结果
    const pingSuccess = Math.random() > 0.1; // 90%概率成功
    this.pingResults.set(deviceId, {
      success: pingSuccess,
      latency: pingSuccess ? 20 + Math.floor(Math.random() * 80) : -1,
      timestamp: Date.now()
    });
    
    // 计算健康分数
    const healthScore = this._calculateHealthScore(deviceId);
    device.healthStatus = healthScore;
    
    // 触发健康状态更新回调
    if (device.onHealthUpdate) {
      device.onHealthUpdate({
        deviceId,
        signalStrength: device.signalStrength,
        pingResult: this.pingResults.get(deviceId),
        healthStatus: healthScore
      });
    }
    
    logger.debug(`模拟设备[${deviceId}]健康检查: 信号强度=${device.signalStrength}, 健康状态=${healthScore}`);
  }

  /**
   * 对设备执行ping测试
   * @param {string} deviceId - 设备ID
   * @private
   */
  _pingDevice(deviceId) {
    const device = this.deviceMap.get(deviceId);
    if (!device || !device.ip) return;
    
    // 记录开始时间
    const startTime = Date.now();
    
    // 模拟ping测试（微信小程序不支持直接ping，使用HTTP请求替代）
    wx.request({
      url: `http://${device.ip}/ping`,
      method: 'GET',
      timeout: 3000, // 3秒超时
      success: () => {
        // 计算延迟
        const latency = Date.now() - startTime;
        
        // 更新ping结果
        this.pingResults.set(deviceId, {
          success: true,
          latency,
          timestamp: Date.now()
        });
      },
      fail: () => {
        // 更新ping结果
        this.pingResults.set(deviceId, {
          success: false,
          latency: -1,
          timestamp: Date.now()
        });
      }
    });
  }

  /**
   * 计算设备健康分数
   * @param {string} deviceId - 设备ID
   * @returns {number} 健康分数
   * @private
   */
  _calculateHealthScore(deviceId) {
    const device = this.deviceMap.get(deviceId);
    const pingResult = this.pingResults.get(deviceId);
    
    if (!device) return HEALTH_STATUS.OFFLINE;
    
    // 设备未连接
    if (device.status !== CONNECTION_STATUS.CONNECTED) {
      return HEALTH_STATUS.OFFLINE;
    }
    
    // 无ping结果或ping失败
    if (!pingResult || !pingResult.success) {
      return HEALTH_STATUS.POOR;
    }
    
    // 根据信号强度和延迟计算健康分数
    const signalScore = Math.min(3, Math.max(0, Math.floor(device.signalStrength / 25)));
    
    let latencyScore;
    if (pingResult.latency < 50) {
      latencyScore = 3; // 优良
    } else if (pingResult.latency < 150) {
      latencyScore = 2; // 良好
    } else {
      latencyScore = 1; // 较差
    }
    
    // 取较低的分数作为最终健康分数
    return Math.min(signalScore, latencyScore);
  }

  /**
   * 连接到WiFi设备
   * @param {string} deviceId - 设备ID
   * @param {Object} options - 连接选项
   * @param {Object} options.deviceInfo - 设备信息
   * @param {string} options.ssid - WiFi SSID
   * @param {string} options.bssid - WiFi BSSID
   * @param {string} options.password - WiFi密码
   * @param {boolean} options.autoReconnect - 是否自动重连
   * @param {Function} options.onSuccess - 连接成功回调
   * @param {Function} options.onFailed - 连接失败回调
   * @param {Function} options.onDisconnected - 断开连接回调
   * @param {Function} options.onReconnectFailed - 重连失败回调
   * @param {Function} options.onHealthUpdate - 健康状态更新回调
   */
  connectToDevice(deviceId, options = {}) {
    // 检查WiFi模块是否初始化
    if (!this.isInitialized) {
      if (options.onFailed) {
        options.onFailed({ errMsg: 'WiFi模块未初始化' });
      }
      return;
    }
    
    // 提取选项
    const { 
      deviceInfo = {},
      ssid, 
      bssid = '', 
      password = '', 
      autoReconnect = true,
      onSuccess,
      onFailed,
      onDisconnected,
      onReconnectFailed,
      onHealthUpdate
    } = options;
    
    // 参数验证
    if (!ssid || !deviceId) {
      if (onFailed) {
        onFailed({ errMsg: '无效的参数' });
      }
      return;
    }
    
    // 更新设备映射
    this.deviceMap.set(deviceId, {
      status: CONNECTION_STATUS.CONNECTING,
      ssid,
      bssid,
      deviceInfo,
      autoReconnect,
      retryCount: 0,
      onConnected: onSuccess,
      onDisconnected,
      onReconnectFailed,
      onHealthUpdate,
      healthStatus: HEALTH_STATUS.OFFLINE
    });
    
    // 开发者工具环境下模拟连接
    if (this.isDevTools) {
      logger.info(`开发者工具环境: 模拟连接WiFi设备[${deviceId}]`);
      
      // 设置模拟延迟
      setTimeout(() => {
        // 90%的概率连接成功
        const isSuccess = Math.random() > 0.1;
        
        if (isSuccess) {
          logger.info(`模拟连接WiFi设备[${deviceId}]成功`);
          
          // 更新设备状态
          const device = this.deviceMap.get(deviceId);
          if (device) {
            device.status = CONNECTION_STATUS.CONNECTED;
            device.ip = '192.168.4.' + Math.floor(Math.random() * 254 + 1);
          }
          
          if (onSuccess) {
            onSuccess({
              wifi: {
                SSID: ssid,
                BSSID: bssid || 'aa:bb:cc:dd:ee:ff',
                signalStrength: 85
              }
            });
          }
          
          // 设备健康检查
          setTimeout(() => {
            this._mockHealthCheck(deviceId);
          }, 1000);
        } else {
          logger.error(`模拟连接WiFi设备[${deviceId}]失败`);
          
          // 更新设备状态
          const device = this.deviceMap.get(deviceId);
          if (device) {
            device.status = CONNECTION_STATUS.ERROR;
          }
          
          if (onFailed) {
            onFailed({ errMsg: '模拟连接失败' });
          }
        }
      }, 1500); // 模拟连接延迟
      
      return;
    }
    
    // 真机环境下连接WiFi
    wx.connectWifi({
      SSID: ssid,
      BSSID: bssid,
      password,
      success: (res) => {
        logger.info(`连接WiFi设备[${deviceId}]成功`, res);
        
        // 连接成功后获取IP地址
        setTimeout(() => {
          this._getDeviceIpAddress(deviceId);
        }, 1000);
        
        // 更新设备状态
        const device = this.deviceMap.get(deviceId);
        if (device) {
          device.status = CONNECTION_STATUS.CONNECTED;
        }
        
        if (onSuccess) {
          onSuccess(res);
        }
      },
      fail: (err) => {
        logger.error(`连接WiFi设备[${deviceId}]失败`, err);
        
        // 更新设备状态
        const device = this.deviceMap.get(deviceId);
        if (device) {
          device.status = CONNECTION_STATUS.ERROR;
        }
        
        if (onFailed) {
          onFailed(err);
        }
      }
    });
  }

  /**
   * 获取设备IP地址
   * @param {string} deviceId - 设备ID
   * @private
   */
  _getDeviceIpAddress(deviceId) {
    const device = this.deviceMap.get(deviceId);
    if (!device) return;
    
    wx.getConnectedWifi({
      success: (res) => {
        if (res.wifi && res.wifi.BSSID === device.bssid) {
          // 获取本机IP地址
          const ip = wx.getStorageSync('deviceIpMap_' + device.bssid) || '192.168.4.1'; // 默认IP
          device.ip = ip;
          
          // 开始健康检查
          this._checkDeviceHealth(deviceId);
        }
      },
      fail: (err) => {
        logger.error(`获取设备[${deviceId}]IP地址失败`, err);
      }
    });
  }

  /**
   * 断开与WiFi设备的连接
   * @param {string} deviceId - 设备ID
   * @param {Function} callback - 断开连接回调
   */
  disconnectFromDevice(deviceId, callback) {
    const device = this.deviceMap.get(deviceId);
    if (!device) {
      if (callback) {
        callback({ success: false, errMsg: '设备未找到' });
      }
      return;
    }
    
    // 更新设备状态
    device.status = CONNECTION_STATUS.DISCONNECTED;
    
    // 停止自动重连
    if (this.reconnectTimers.has(deviceId)) {
      clearTimeout(this.reconnectTimers.get(deviceId));
      this.reconnectTimers.delete(deviceId);
    }
    
    // 开发者工具环境下模拟断开连接
    if (this.isDevTools) {
      logger.info(`开发者工具环境: 模拟断开与WiFi设备[${deviceId}]的连接`);
      
      setTimeout(() => {
        if (callback) {
          callback({ success: true });
        }
      }, 500);
      
      return;
    }
    
    // 真机环境下断开WiFi连接
    wx.disconnectWifi({
      success: (res) => {
        logger.info(`断开WiFi设备[${deviceId}]成功`, res);
        
        if (callback) {
          callback({ success: true });
        }
      },
      fail: (err) => {
        logger.error(`断开WiFi设备[${deviceId}]失败`, err);
        
        if (callback) {
          callback({ success: false, errMsg: err.errMsg });
        }
      }
    });
  }

  /**
   * 发送命令到WiFi设备
   * @param {string} deviceId - 设备ID
   * @param {Object} command - 命令对象
   * @param {Object} options - 选项
   * @param {Function} options.onSuccess - 成功回调
   * @param {Function} options.onFailed - 失败回调
   */
  sendCommand(deviceId, command, options = {}) {
    const device = this.deviceMap.get(deviceId);
    if (!device || device.status !== CONNECTION_STATUS.CONNECTED) {
      if (options.onFailed) {
        options.onFailed({ errMsg: '设备未连接' });
      }
      return;
    }
    
    // 确保设备有IP地址
    if (!device.ip) {
      logger.error(`设备[${deviceId}]IP地址未知，无法发送命令`);
      if (options.onFailed) {
        options.onFailed({ errMsg: '设备IP地址未知' });
      }
      return;
    }
    
    // 开发者工具环境下模拟发送命令
    if (this.isDevTools) {
      logger.info(`开发者工具环境: 模拟向设备[${deviceId}]发送命令`, command);
      
      // 设置模拟延迟
      setTimeout(() => {
        // 95%的概率发送成功
        const isSuccess = Math.random() > 0.05;
        
        if (isSuccess) {
          logger.info(`模拟向设备[${deviceId}]发送命令成功`);
          
          if (options.onSuccess) {
            options.onSuccess({ data: { success: true } });
          }
        } else {
          logger.error(`模拟向设备[${deviceId}]发送命令失败`);
          
          if (options.onFailed) {
            options.onFailed({ errMsg: '模拟发送命令失败' });
          }
        }
      }, 300); // 模拟网络延迟
      
      return;
    }
    
    // 真机环境下发送HTTP请求
    wx.request({
      url: `http://${device.ip}/command`,
      method: 'POST',
      data: command,
      timeout: 5000,
      success: (res) => {
        logger.info(`向设备[${deviceId}]发送命令成功`, res);
        
        if (options.onSuccess) {
          options.onSuccess(res);
        }
      },
      fail: (err) => {
        logger.error(`向设备[${deviceId}]发送命令失败`, err);
        
        // 命令失败，检查设备健康状态
        this._checkDeviceHealth(deviceId);
        
        if (options.onFailed) {
          options.onFailed(err);
        }
      }
    });
  }

  /**
   * 获取设备连接状态
   * @param {string} deviceId - 设备ID
   * @returns {number} 连接状态
   */
  getConnectionStatus(deviceId) {
    debugger
    // 如果在开发者工具中，使用模拟状态
    if (this.isDevTools) {
      // 检查是否有模拟状态
      const mockStatus = connectionStatus.mockConnectionStatus(deviceId);
      if (mockStatus) {
        return mockStatus.rawWifiStatus;
      }
      
      // 生成随机状态
      const randomStatus = [
        CONNECTION_STATUS.DISCONNECTED,
        CONNECTION_STATUS.CONNECTING,
        CONNECTION_STATUS.CONNECTED,
        CONNECTION_STATUS.ERROR
      ];
      const randomIndex = Math.floor(Math.random() * randomStatus.length);
      return randomStatus[randomIndex];
    }
    
    // 从设备映射中获取状态
    const device = this.deviceMap.get(deviceId);
    return device && device.status !== undefined ? device.status : CONNECTION_STATUS.DISCONNECTED;
  }

  /**
   * 获取设备健康状态
   * @param {string} deviceId - 设备ID
   * @returns {number} 健康状态
   */
  getHealthStatus(deviceId) {
    const device = this.deviceMap.get(deviceId);
    return device ? device.healthStatus : HEALTH_STATUS.OFFLINE;
  }

  /**
   * 获取所有已连接的设备
   * @returns {Array} 设备列表
   */
  getConnectedDevices() {
    const connectedDevices = [];
    
    this.deviceMap.forEach((device, deviceId) => {
      if (device.status === CONNECTION_STATUS.CONNECTED) {
        connectedDevices.push({
          deviceId,
          ssid: device.ssid,
          bssid: device.bssid,
          signalStrength: device.signalStrength,
          healthStatus: device.healthStatus,
          deviceInfo: device.deviceInfo
        });
      }
    });
    
    return connectedDevices;
  }
}

// 导出WiFi服务单例
let instance = null;
module.exports = {
  getInstance: function() {
    if (!instance) {
      instance = new WifiService();
    }
    return instance;
  },
  CONNECTION_STATUS,
  HEALTH_STATUS
}; 